package gzc.netty4.server;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.util.ReferenceCountUtil;

import java.io.UnsupportedEncodingException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * Created by designerpc on 2016/11/26.
 */
public class Netty4ServerHandler extends ChannelInboundHandlerAdapter {

    final public static String UTF8 = "utf-8";

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
//        readOneMsg(ctx, msg);
//        readOneMsg2(ctx, msg);
//        readOneMsg3(ctx, msg);
//        readOneMsg4(ctx, msg);
//        readOneMsg5(ctx, msg);
        readOneMsg6(ctx, msg);
    }

    /*例子1*/
    private void readOneMsg(ChannelHandlerContext ctx, Object msg) throws Exception {
        ByteBuf buf = (ByteBuf) msg;
        final int len = buf.readShort();
        System.out.printf("len=%#x\n", len);

        byte[] data = new byte[len];
        buf.readBytes(data, 0, len);
        final String str = new String(data, UTF8);
        System.out.printf("len=%s\n", str);
    }

    /*例子2*/
    private void readOneMsg2(ChannelHandlerContext ctx, Object msg) throws Exception {
        ByteBuf buf = (ByteBuf) msg;
        final int len = buf.readableBytes();
        System.out.printf("len=%#x\n", len);

        byte[] data = new byte[len];
        buf.readBytes(data, 0, len);
        final String str = new String(data, UTF8);
        System.out.printf("len=%s\n", str);
    }

    /*例子3*/
    private void readOneMsg3(ChannelHandlerContext ctx, Object msg) throws Exception {
        ByteBuf buf = (ByteBuf) msg;
        // 包含了头长的整个消息长度，减2得到包体长度
        final int len = buf.readShort() - 2;
        System.out.printf("len=%#x\n", len);

        byte[] data = new byte[len];
        buf.readBytes(data, 0, len);
        final String str = new String(data, UTF8);
        System.out.printf("len=%s\n", str);
    }

    /*例子4*/
    private void readOneMsg4(ChannelHandlerContext ctx, Object msg) throws Exception {
        ByteBuf buf = (ByteBuf) msg;
        final int header1 = buf.readShort();
        System.out.printf("header1=%#x\n", header1);

        final int len = buf.readMedium();
        System.out.printf("len=%#x\n", len);

        byte[] data = new byte[len];
        buf.readBytes(data, 0, len);
        final String str = new String(data, UTF8);
        System.out.printf("len=%s\n", str);
    }

    /*例子5*/
    private void readOneMsg5(ChannelHandlerContext ctx, Object msg) throws Exception {
        ByteBuf buf = (ByteBuf) msg;

        final int len = buf.readMedium();
        System.out.printf("len=%#x\n", len);

        final int header1 = buf.readShort();
        System.out.printf("header1=%#x\n", header1);

        byte[] data = new byte[len];
        buf.readBytes(data, 0, len);
        final String str = new String(data, UTF8);
        System.out.printf("len=%s\n", str);
    }

    /*例子6，例子7*/
    private void readOneMsg6(ChannelHandlerContext ctx, final Object msg) throws Exception {
        executorService.execute(new Runnable() {
            @Override
            public void run() {
                // 休眠随机1到10秒
                try {
                    Thread.sleep(1000 * (int) (1 + Math.random() * (10 - 1 + 1)));
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                ByteBuf buf = (ByteBuf) msg;

                final int len = buf.readableBytes() - 1;
                System.out.printf("len=%#x\n", len);

                final int header2 = buf.readByte();
                System.out.printf("header2=%#x\n", header2);

                byte[] data = new byte[len];
                buf.readBytes(data, 0, len);
                try {
                    String str = new String(data, UTF8);
                    System.out.printf("data=%s\n", str);
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }

                ReferenceCountUtil.release(buf);
            }
        });
    }

    final private ExecutorService executorService =
            Executors.newFixedThreadPool(4);

}
